home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
CRS
/
crs08.d81
/
unzip.c
< prev
next >
Wrap
Text File
|
2009-10-10
|
12KB
|
453 lines
#include "stdio.h"
#include "unzip.h"
struct zhdr {
long signature;
int version_needed;
int gp_flag;
int method;
int time;
int date;
long crc32;
long comp_size;
long file_size;
int fn_len;
int extra_len;
} zhdr;
long tot_comp_size,
tot_file_size;
int num_of_files;
char *buffer; /* change to dynamic allocation */
char *bufpt; /* indexes thru above */
char out_fname[80];
char file_spec[80];
long bytes_in,
bytes_out;
unsigned int bits_left,
s_r;
int zipeof;
int extr_flag;
unsigned int buf_size;
unsigned int scrn_upd_cnt;
FILE *infd;
FILE *outfd;
char months[12][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
char method_name[7][7] = {
"Stored", "Shrunk", "Reduc1", "Reduc2", "Reduc3", "Reduc4", "Implod"};
/* ========================================================================= */
void
fatal_exit(message)
char *message;
{
printf(message);
exit();
}
void
inibuf()
{
int i;
for (i = 0; i < buf_size; i++)
buffer[i] = 0; /* init the buffer */
}
int
status(fn)
char *fn;
{
#ifdef MSC
if (access(fn, 0) == 0)
return (EXISTS);
else
return (DOES_NOT_EXIST);
#else
/* do it without the benefit of the 'access' function... */
FILE *temp_id;
if ((temp_id = fopen(fn, READ_ACCESS)) == NULL)
return (DOES_NOT_EXIST);
else {
fclose(temp_id);
return (EXISTS);
}
#endif
}
int
open_out()
{
unsigned char answ;
if (status(out_fname) == EXISTS) {
printf(" Overwrite existing file?\007 ");
while (((answ = (toupper(getc(stdin)))) != 'Y') && (answ != 'N'));
if (answ != 'Y') {
printf("\n");
return (FAILURE);
}
}
if ((outfd = fopen(out_fname, WRITE_ACCESS)) == NULL) {
printf("\n** Error, cannot open file %s", out_fname);
return (FAILURE);
} else
return (SUCCESS);
}
int
next_bit()
{
int bit;
if (bits_left-- == 0) {
if ((s_r = getc(infd)) == EOF)
fatal_exit("\nUnexpected EOF\n");
bits_left = 7;
if (++bytes_in >= zhdr.comp_size)
zipeof = -1;
}
bit = s_r & 0x0001;
s_r = (s_r >> 1);
return (bit);
}
void
update_screen()
{
printf("\015%dk", (unsigned int) (bytes_out / 1024L));
}
void
put_ch(ch)
char ch;
{
if (buf_size) {
*bufpt++ = ch;
if ((unsigned int) bufpt - (unsigned int) buffer >= buf_size)
bufpt = buffer;
}
putc(ch, outfd);
bytes_out++;
if (scrn_upd_cnt++ > 1023) {
scrn_upd_cnt -= 1024;
update_screen();
}
}
int
get_num(nbits)
int nbits;
{
unsigned int tot,
i;
tot = 0;
for (i = 0; i < nbits; i++) {
tot = tot >> 1;
if (next_bit() != 0)
tot |= 0x8000;
}
return (tot >> (16 - nbits));
}
int
proc_header()
{
/* Read in the whole local header structure (starts with 'signature') */
fread(&zhdr.signature, 1, sizeof(zhdr), infd);
if (zhdr.signature == CENTRAL_SIGNATURE)
return (END_OF_ZIP);
if (zhdr.signature != LOCAL_SIGNATURE)
fatal_exit("\nInvalid ZIP file format.");
if (zhdr.version_needed > THIS_VERSION)
fatal_exit("\nNeed newer version of this program.");
fread(out_fname, 1, zhdr.fn_len, infd);
out_fname[zhdr.fn_len] = 0; /* make it a 'real' string */
if (STRCHR(out_fname, '.') == 0) /* guarantee it has a '.' */
strcat(out_fname, ".");
fseek(infd, (long) zhdr.extra_len, CURRENT);/* skip the extra field */
return (SUCCESS);
}
/* ========================================================================= */
void
unstore()
{ /* extract a file which is STORED */
buf_size = 0;
bits_left = 0; /* not really necessary */
s_r = 0; /* likewise */
printf("\n");
while (bytes_out < zhdr.file_size)
put_ch(getc(infd));
free(buffer);
}
/* ========================================================================= */
/*
* match() compares a pattern with a string. Wildcards accepted in the pattern are: "*" for zero or more arbitrary
* characters; "?" for any one characters. Unlike the MS-DOS wildcard match, "*" is correctly handled even if it
* isn't at the end of the pattern. ".' is not special.
*
* Originally written by Jeff Damens of Columbia University Center for Computing Activities. Taken from the source code
* for C-Kermit version 4C.
*/
/*
* Note: I left this routine intact, but did add a "." character to either a filename or match pattern that originally
* had a blank extension (done elsewhere, before this routine is called). This provides a minimum expected
* compatibility with MS-DOS conventions, eg that "*.*" refers to all files, not all files except those with blank
* extensions. - SGG
*/
int
match(string, pattern)
char *string,
*pattern;
{
char *psave,
*ssave; /* back up pointers for failure */
psave = ssave = ((char *) 0);
while (1) {
for (; *pattern == *string; pattern++, string++) /* skip first */
if (*string == '\0')
return (1); /* end of strings, succeed */
if (*string != '\0' && *pattern == '?') {
pattern++; /* '?', let it match */
string++;
} else if (*pattern == '*') { /* '*' ... */
psave = ++pattern; /* remember where we saw it */
ssave = string; /* let it match 0 chars */
} else if (ssave != ((char *) 0) && *ssave != '\0') { /* if not at end */
/* ...have seen a star */
string = ++ssave; /* skip 1 char from string */
pattern = psave; /* and back up pattern */
} else
return (0); /* otherwise just fail */
}
}
void
type_out_fname()
{ /* type output file name AND it's size */
printf(" %12s (%3dk)", out_fname, (zhdr.file_size + 1023) / 1024);
}
/* ======================================================================== */
void
extract1()
{
if (STRCHR(out_fname, '.') == NULL)
strcat(out_fname, ".");
if (!(match(out_fname, file_spec))) { /* does it match spec'd filespec ? */
printf("\015** Skipping: ");
type_out_fname();
printf("\n");
fseek(infd, zhdr.comp_size, CURRENT); /* skip the member */
return;
}
bytes_out = 0L;
bytes_in = 0L;
zipeof = 0;
scrn_upd_cnt = 1024;
switch (zhdr.method) {
case STORED:
printf("\015Extracting: ");
type_out_fname();
if (open_out() == FAILURE) {
fseek(infd, zhdr.comp_size, CURRENT); /* skip the member */
return;
}
unstore();
break;
case SHRUNK:
printf("\015Stretching: ");
type_out_fname();
if (open_out() == FAILURE) {
fseek(infd, zhdr.comp_size, CURRENT); /* skip the member */
return;
}
ovloader("unshrink");
break;
case IMPLODED:
printf("\015Exploding: ");
type_out_fname();
if (open_out() == FAILURE) {
fseek(infd, zhdr.comp_size, CURRENT); /* skip the member */
return;
}
ovloader("explode");
break;
case REDUCE_1:
case REDUCE_2:
case REDUCE_3:
case REDUCE_4:
printf("\015Oxidizing: ");
type_out_fname();
if (open_out() == FAILURE) {
fseek(infd, zhdr.comp_size, CURRENT); /* skip the member */
return;
}
ovloader("unreduce");
break;
default:
printf("\015** Skipping:");
type_out_fname();
printf(" (Unknown compression method)\n");
fseek(infd, zhdr.comp_size, CURRENT); /* skip the member */
return;
}
fclose(outfd);
return;
}
/* ========================================================================= */
/* list a member file */
void
list1()
{
int yr,
mo,
dy;
int hh,
mm;
int s_f;
int kbytes;
char f_n[13],
f_ext[4];
char *dotpos;
yr = (zhdr.date >> 9) & 0x7f; /* extract date from bit mapped fields */
mo = (zhdr.date >> 5) & 0x0f;
dy = zhdr.date & 0x1f;
hh = (zhdr.time >> 11) & 0x1f; /* likewise the time */
mm = (zhdr.time >> 5) & 0x3f;
s_f = (int) (100L - ((100L * zhdr.comp_size) / zhdr.file_size));
kbytes = (int) ((zhdr.file_size + 1023L) / 1024L);
tot_comp_size += zhdr.comp_size;
tot_file_size += zhdr.file_size;
num_of_files++;
strncpy(f_n, out_fname, 13); /* should copy the null, too */
dotpos = STRCHR(f_n, '.');
if (dotpos == NULL)
strcpy(f_ext, " ");
else {
*dotpos = 0;
strncpy(f_ext, dotpos + 1, 4); /* should copy the null, too */
}
printf("%-8s.%3s %7ld %4dk %6s %7ld %3d%% %2d %3s %2d %2d:%02d %08lx\n",
f_n, f_ext, zhdr.file_size, kbytes, &method_name[zhdr.method][0],
zhdr.comp_size, s_f, dy, &months[mo - 1][0], (yr + 80) % 100, hh, mm, zhdr.crc32);
fseek(infd, zhdr.comp_size, CURRENT); /* skip the member */
}
/* ========================================================================= */
void
main(argc, argv)
int argc;
unsigned char *argv[];
{
unsigned char zip_file_name[80];
int tot_disk_size,
tot_s_f;
int byte_1, byte_2;
int exe_sz_mod_512, exe_sz_x_512;
if ((argc < 2) || (argc > 3)) {
printf("\nUNZIP v0.99 Copyright 1989 S. Greenberg\n");
printf(" may be reproduced for non-profit use.\n");
printf("\nUsage: UNZIP <filename[.zip]> [<afn>]\n");
printf("\nExtracts all members matching <afn> from the specified ZIPfile.");
printf("\n If <afn> is not present, a directory of the members will be displayed.\n");
exit();
}
printf("\nUNZIP v0.99 SGG 09/11/89\n");
strcpy(zip_file_name, argv[1]);
if (STRCHR(zip_file_name, '.') == 0)
strcat(zip_file_name, ".ZIP");
if ((infd = fopen(zip_file_name, READ_ACCESS)) == NULL) {
printf("\nCan't open input file: %s", zip_file_name);
exit();
}
printf("\n ZIPfile = %s\n\n", zip_file_name);
if (argc == 2) {
strcpy(file_spec, "*.*"); /* not spec'd means all files */
extr_flag = 0;
printf("Name Length Disk Method Stored Saved Date Time CRC\n");
printf("============ ======= ==== ====== ======= ===== ========= ===== ========\n");
tot_comp_size = 0L;
tot_file_size = 0L;
num_of_files = 0;
} else {
strcpy(file_spec, argv[2]); /* filespec for extraction */
if (STRCHR(file_spec, '.') == 0)
strcat(file_spec, ".");
extr_flag = -1;
}
if ((byte_1 = getc(infd)) == EOF)
fatal_exit("\nFile is empty.");
if ((byte_1 == 'M') && ((byte_2 = getc(infd)) == 'Z')) {
fread(&exe_sz_mod_512, 1, 2, infd); /* skip EXE section of SXF types */
fread(&exe_sz_x_512, 1, 2, infd);
fseek(infd, (long) (exe_sz_x512 * 512 + exe_sz_mod_512 -512 -6), CURRENT);
} else
fseek(infd, 0L, BEGINNING); /* regular zip, rewind to beginning */
while (proc_header() != END_OF_ZIP) {
if (extr_flag)
extract1();
else
list1();
}
if (!extr_flag) {
tot_disk_size = (int) ((tot_file_size + 1023L) / 1024L);
tot_s_f = (int) (100L - ((100L * tot_comp_size) / tot_file_size));
printf("============ ======= ==== ======= =====\n");
printf("Total %3d %7ld %4dk %7ld %3d%%\n",
num_of_files, tot_file_size, tot_disk_size, tot_comp_size, tot_s_f);
}
fclose(infd);
}